/*
 * SemanticAnalysisVisitor.cpp
 *
 *  Created on: Nov 23, 2010
 *      Author: dhovemey
 */

#include <cassert>
#include "util/Error.h"
#include "util/CompositeException.h"
#include "fe/ASTUtil.h"
#include "fe/ASTNode.h"
#include "fe/SymbolTable.h"
#include "fe/SemanticAnalysisVisitor.h"

SemanticAnalysisVisitor::SemanticAnalysisVisitor()
	: m_symtab(0)
{

}

SemanticAnalysisVisitor::~SemanticAnalysisVisitor()
{

}

bool SemanticAnalysisVisitor::error()
{
	return !m_exceptionList.empty();
}

CompositeException *SemanticAnalysisVisitor::getException()
{
	CompositeException *cex = new CompositeException();
	for (ExceptionList::iterator i = m_exceptionList.begin(); i != m_exceptionList.end(); i++) {
		cex->addAndAdopt(*i);
	}
	return cex;
}

void SemanticAnalysisVisitor::visitClass(ASTNode * n)
{
	m_symtab = createClassOrModuleSymbolTable(n);
	PreorderASTNodeVisitor::visitClass(n);
}

void SemanticAnalysisVisitor::visitModule(ASTNode * n)
{
	m_symtab = createClassOrModuleSymbolTable(n);
	PreorderASTNodeVisitor::visitModule(n);
}

void SemanticAnalysisVisitor::visitVarRefExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitIntLiteralExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitBooleanLiteralExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitSymbolLiteralExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitStringLiteralExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitSelfRefExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitField(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitVar(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitImport(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitStaticImport(ASTNode*)
{

}

void SemanticAnalysisVisitor::visitNilExpr(ASTNode*)
{

}

void SemanticAnalysisVisitor::handleException()
{
	Exception *ex = Error::getException();
	assert(ex != 0);
	m_exceptionList.push_back(ex);
	Error::raise(0);
}

SymbolTable *SemanticAnalysisVisitor::createClassOrModuleSymbolTable(ASTNode *n)
{
	SymbolTable *symtab = new SymbolTable(0);
	n->adoptSymbolTable(symtab);

	// add entries for members (fields and methods)
	ASTUtil::ASTNodeList memberList;
	ASTUtil::findChildren(n, ASTUtil::IsMember(), memberList);
	for (ASTUtil::ASTNodeList::iterator i = memberList.begin(); i != memberList.end(); i++) {
		if (!symtab->addMember(*i)) {
			handleException();
		}
	}

	return symtab;
}
